package com.stephen.redisdemo.service.impl;

import com.google.gson.Gson;
import com.stephen.redisdemo.domain.Commodity;
import com.stephen.redisdemo.mapper.CommodityMapper;
import com.stephen.redisdemo.service.CommodityService;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.data.redis.core.RedisTemplate;
import org.springframework.data.redis.core.ValueOperations;
import org.springframework.stereotype.Service;

import java.util.List;
import java.util.concurrent.TimeUnit;

/**
 * Created by ssc on 2020-03-30 10:40 .
 * Description:
 */
@Service
public class CommodityServiceImpl implements CommodityService {

    @Autowired
    private CommodityMapper commodityMapper;

    @Autowired
    private RedisTemplate redisTemplate;

    @Override
    public Commodity findById(Integer id) {
        ValueOperations opsForValue = redisTemplate.opsForValue();
        Object redisValue = opsForValue.get(String.valueOf(id));
        // 缓存中有数据，直接返回
        if (redisValue != null) {
            Commodity commodity = new Gson().fromJson((String) redisValue, Commodity.class);
            commodity.setFromDB(false);
            return commodity;
        }
        // redis中没有数据,查数据库
        Commodity commodity = commodityMapper.findById(id).get();
        // 数据库中有数据
        if (commodity != null) {
            // 设置随机时间,可以解决缓存雪崩问题
            // int expireTime = 60 + new Random().nextInt(60);

            opsForValue.set(String.valueOf(id),new Gson().toJson(commodity), 60,TimeUnit.SECONDS);
        } else {
            // 存一个null值
            opsForValue.set(String.valueOf(id),null, 20,TimeUnit.SECONDS);
        }
        return commodity;
    }

    /**
     * 互斥锁 mutex
     * 获取redis中的值
     * @return
     */
    public Object get(String key) {
        String KEY_MUTEX = "key_mutex";
        Object redisValue = redisTemplate.opsForValue().get(key);
        if (redisValue == null) { // 缓存失效
            // setnx 要设置过期时间，防止delete失败时，无法再次load db
            if (redisTemplate.opsForValue().setIfAbsent(KEY_MUTEX,1,1,TimeUnit.SECONDS)) {
                // redis中没有数据,查数据库
                Commodity commodity = commodityMapper.findById(Integer.valueOf(key)).get();
                redisTemplate.opsForValue().set(key,new Gson().toJson(commodity),1,TimeUnit.SECONDS);
                redisTemplate.delete(KEY_MUTEX);
            } else {
                // 其它线程等待50ms后，再获取缓存
                try {
                    TimeUnit.MILLISECONDS.sleep(50);
                    redisValue = redisTemplate.opsForValue().get(key);
                } catch (InterruptedException e) {
                    e.printStackTrace();
                }
            }
        }
        return redisValue;
    }

    @Override
    public List<Commodity> findAll() {
        List<Commodity> commodityList = commodityMapper.findAll();

        return commodityList;
    }

    @Override
    public void deleteById(Integer id) {
        commodityMapper.deleteById(id);
    }


}
